import os
import redis
import sys
import ast

from database.rdb_wrapper import RedisDB

class RedisClient(RedisDB):
    
    def __init__(self, port="", unix_socket=None, db_id=-1):
        super().__init__(int(port), unix_socket, db_id)
        
    def set_item(self, key, value):
        return self._set_value(key, value)
    
    def get_value(self, key):
        "Because the stored value is list type, so we pick the first element"
        return ast.literal_eval(self._get_value(key).decode())[0]
    
    def get_int_value(self, key):
        return self._get_value(key)
    
    def batch_set_items(self, items={}):
        return self._batch_set_values(items)
    
    def inc_int_value(self, key):
        return self._inc_value(key)
    
    def dec_int_value(self, key):
        return self._dec_value(key)
    
    def exists(self, key):
        return self._exists(key)
    
    def store_item(self, key, value):
        return self._store_value(key, value)
    
    def get_all_item(self):
        return self._get_all()
    
    def del_item(self, key):
        return self._del_key(key)

class CmdHandleBase(object):
    
    def __init__(self, unix_socket=None, port="0", db_id=0):
        
        self.__name_dep_map = {}
        self.__link_dep_map = {}
        self.__cmd_dep_map = {}
        
        
        self.__name_dep_db_inst = RedisClient(port=port, unix_socket=unix_socket, db_id=db_id+1)
        self.__link_dep_db_inst = RedisClient(port=port, unix_socket=unix_socket, db_id=db_id+2)
        self.__cmd_dep_db_inst = RedisClient(port=port, unix_socket=unix_socket, db_id=db_id+3)
        
    def get_name_dep(self):
        if not self.__name_dep_map:
            self.__name_dep_map = self.__name_dep_db_inst.get_all_item()
        return self.__name_dep_map
    
    def get_link_dep(self):
        if not self.__link_dep_map:
            self.__link_dep_map = self.__link_dep_db_inst.get_all_item()
        return self.__link_dep_map
    
    def get_cmd_dep(self):
        if not self.__cmd_dep_map:
            self.__cmd_dep_map = self.__cmd_dep_db_inst.get_all_item()
        return self.__cmd_dep_map
    
    def set_name_dep(self, name_md5="", name=""):
        self.__name_dep_db_inst.set_item(key=name_md5, value=name)

    def set_link_dep(self, name_md5="", links=[]):
        self.__link_dep_db_inst.set_item(key=name_md5, value=links)
    
    def set_cmd_dep(self, name_md5="", cmd=[]):
        self.__cmd_dep_db_inst.set_item(key=name_md5, value=cmd)
    
    def del_name_dep(self, name_md5=""):
        self.__name_dep_db_inst.del_item(key=name_md5)
    
    def del_link_dep(self, name_md5=""):
        self.__link_dep_db_inst.del_item(key=name_md5)
    
    def del_cmd_dep(self, name_md5=""):
        self.__cmd_dep_db_inst.del_item(key=name_md5)
        
    def update_name_dep(self, name_md5="", value=""):
        if not value:
            return
        self.__name_dep_db_inst.store_item(name_md5, value)
    
    def update_link_dep(self, name_md5="", value=""):
        if not value:
            return
        self.__link_dep_db_inst.store_item(name_md5, value)
    
    def update_cmd_dep(self, name_md5="", value=""):
        if not value:
            return
        self.__cmd_dep_db_inst.store_item(name_md5, value)
    
    def sync_all_dep(self):
        self.__name_dep_map = {}
        self.__link_dep_map = {}
        self.__cmd_dep_map = {}
        self.__name_dep_map = self.get_name_dep()
        self.__link_dep_map = self.get_link_dep()
        self.__cmd_dep_map = self.get_cmd_dep()
    
    def is_name_exists(self, name_md5=""):
        self.__name_dep_db_inst.exists(key=name_md5)
    
    def is_link_exists(self, name_md5=""):
        self.__link_dep_db_inst.exists(key=name_md5)
    
    def is_cmd_exists(self, name_md5=""):
        self.__cmd_dep_db_inst.exists(key=name_md5)

class GCCCmdDBHandler(CmdHandleBase):
    def __init__(self, port="0", unix_socket=None, db_id=10):
        super(GCCCmdDBHandler, self).__init__(unix_socket=unix_socket, port=port, db_id=db_id)

class ClangCmdDBHandler(CmdHandleBase):
    def __init__(self, port="0", unix_socket=None, db_id=20):
        super(ClangCmdDBHandler, self).__init__(port=port, unix_socket=unix_socket, db_id=db_id)

class LDCmdDBHandler(CmdHandleBase):
    def __init__(self, unix_socket=None, port="0", db_id=30):
        super(LDCmdDBHandler, self).__init__(port=port, unix_socket=unix_socket, db_id=db_id)

class ARCmdDBHandler(CmdHandleBase):
    def __init__(self, unix_socket=None, port="0", db_id=40):
        super(ARCmdDBHandler, self).__init__(port=port, unix_socket=unix_socket, db_id=db_id)
        
class RanlibCmdDBHandler(CmdHandleBase):
    def __init__(self, unix_socket=None, port="0", db_id=50):
        super(RanlibCmdDBHandler, self).__init__(port=port, unix_socket=unix_socket, db_id=db_id)

class StripCmdDBHandler(CmdHandleBase):
    def __init__(self, unix_socket=None, port="0", db_id=60):
        super(StripCmdDBHandler, self).__init__(unix_socket, port, db_id)
        

class FileCacheDBHandler(object):
    def __init__(self, unix_socket="",  port="0", db_id=0):
        
        self.__file_cache_map = {}
        self.__cache_db_inst = RedisClient(unix_socket=unix_socket, port=port, db_id=db_id)
    
    def get_cache_map(self):
        if not self.__file_cache_map:
            self.__file_cache_map = self.__cache_db_inst.get_all_item()
        return self.__file_cache_map
    
    def set_cache_map(self, file_md5="", file_path=""):
        self.__cache_db_inst.set_item(key=file_md5, value=file_path)
    
    def del_cache_map(self, key=""):
        if self.__cache_db_inst.exists(key=key):
            self.__cache_db_inst.del_item(key=key)
    
    def is_exists(self, key=""):
        if self.__cache_db_inst.exists(key=key):
            return True
        return False